﻿using DrawTools.Serialize;
using System;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;

namespace DrawTools.Tools
{
    /// <summary>
    /// 矩形
    /// </summary>
    [SerializerType(typeof(DrawRectangleSerializer))]
    public sealed class RectangleDrawTool : DrawGeometryBase
    {
        #region 字段

        private Point? topLeft, bottomRight;
        protected override Point BeginingPoint
        {
            get
            {
                if (base.BeginingPoint.X != 0) return base.BeginingPoint;
                if (this.topLeft == null || this.bottomRight == null) return new Point();
                var point = topLeft.Value;
                if (topLeft.Value.X * topLeft.Value.Y > bottomRight.Value.X * bottomRight.Value.Y)
                {
                    point = bottomRight.Value;
                }
                return point;
            }
        }

        #endregion 字段

        public RectangleDrawTool(DrawingCanvas drawingCanvas) : base(drawingCanvas)
        {
            DrawingToolType = DrawToolType.Rectangle;

            // 准备要处理的事件
            CanTouchDown = true;
        }

        #region 鼠标键盘事件

        public override bool OnKeyDown(Key key)
        {
            if (key != Key.LeftShift || !bottomRight.HasValue)
                return false;

            return OnTouchMove(bottomRight.Value);
        }

        public override bool OnKeyUp(Key key)
        {
            if (key != Key.LeftShift || !bottomRight.HasValue)
                return false;

            return OnTouchMove(bottomRight.Value);
        }

        public override bool OnTouchLeave(Point point, bool isLeaved = false)
        {
            if (!bottomRight.HasValue)
                drawingCanvas.DeleteVisual(this);
            else
            {
                var figure = pathGeometry.Figures[0];

                var line = new LineSegment(new Point(bottomRight.Value.X, topLeft.Value.Y), IsStroked);
                figure.Segments.Add(line);

                line = new LineSegment(bottomRight.Value, IsStroked);
                figure.Segments.Add(line);

                line = new LineSegment(new Point(topLeft.Value.X, bottomRight.Value.Y), IsStroked);
                figure.Segments.Add(line);

                geometry = geometry.GetWidenedPathGeometry(Pen);
                Draw();
            }

            drawingCanvas.DeleteWorkingDrawTool(this);

            IsFinish = true;

            CanTouchDown = false;
            CanTouchMove = false;
            CanTouchLeave = false;
            CanKeyDown = false;
            CanKeyUp = false;

            if (TouchId == 0 && drawingCanvas.IsMouseCaptured)
                drawingCanvas.ReleaseMouseCapture();

            return true;
        }

        public override bool OnTouchDown(int touchId, Point point)
        {
            TouchId = touchId;

            if (!topLeft.HasValue)
            {
                drawingCanvas.AddWorkingDrawTool(this);



                topLeft = point;

                geometry = new PathGeometry();

                var figure = new PathFigure { StartPoint = point, IsClosed = true };
                pathGeometry.Figures.Add(figure);

                CanTouchMove = true;
                CanKeyDown = true;
                CanKeyUp = true;

                if (TouchId != 0 || !drawingCanvas.CaptureMouse())
                    CanTouchLeave = true;

                drawingCanvas.AddVisual(this);
            }
            else
                return OnTouchLeave(point);

            return true;
        }

        public override bool OnTouchMove(Point point)
        {
            var dc = RenderOpen();

            var startPoint = topLeft.Value;

            if (Keyboard.IsKeyDown(Key.LeftShift))
            {
                var len = Math.Min(Math.Abs(point.X - startPoint.X), Math.Abs(point.Y - startPoint.Y));
                point = new Point(startPoint.X + (point.X > startPoint.X ? len : -len), startPoint.Y + (point.Y > startPoint.Y ? len : -len));
            }

            if ((startPoint - point).Length > Pen.Thickness)
            {
                bottomRight = point;
                dc.DrawRectangle(null, Pen, new Rect(startPoint, point));
            }

            dc.Close();

            return true;
        }

        #endregion 鼠标键盘事件
    }
}